package gang.org.springframework.framework.bean;

import gang.org.springframework.framework.factory.GangConstructorArgumentValues;
import gang.org.springframework.framework.support.GangResolvableType;

import java.lang.reflect.Executable;
import java.lang.reflect.Method;

/**
 * @author gang.chen
 * @description
 * @Date 2021/6/14 20:36
 */
public class GangRootBeanDefinition extends GangAbstractBeanDefinition {

    public volatile Class<?> resolvedTargetType;

    public volatile GangResolvableType targetType;

    public Executable resolvedConstructorOrFactoryMethod;

    public boolean isFactoryMethodUnique;

    public volatile Method factoryMethodToIntrospect;

    public volatile GangResolvableType factoryMethodReturnType;

    public volatile Boolean isFactoryBean;

    public volatile boolean stale;

    public final Object constructorArgumentLock = new Object();

    public final Object postProcessingLock = new Object();

    public boolean postProcessed = false;

    public GangRootBeanDefinition(Class beanClass){
        setBeanClass(beanClass);
    }

    public GangRootBeanDefinition() {
        super();
    }

    @Override
    public GangRootBeanDefinition cloneBeanDefinition() {
        return new GangRootBeanDefinition(this);
    }

    public GangRootBeanDefinition(GangRootBeanDefinition original){
        //TODO
        super(original);

        /**
         * 业务意义
         * 1）springboot完成工厂类加载后，生成三类bean对象，分别是AnnotatedGenericBeanDefinition，ConfigurationClassBeanDefinition，RootBeanDefinition
         * 2）通过对象转换的方式，将以上三类BeanDefinition统一转为RootBeanDefinition，方便后续统一处理
         * */

        this.isFactoryMethodUnique = original.isFactoryMethodUnique;
        this.factoryMethodToIntrospect = original.factoryMethodToIntrospect;

    }

    public GangRootBeanDefinition(GangBeanDefinition original){
        super(original);
    }

    public Class<?> getTargetType(){
        if (this.resolvedTargetType != null) {
            return this.resolvedTargetType;
        }

        GangResolvableType targetType = this.targetType;

        return targetType != null ? targetType.resolve() : null;
    }

    public void setUniqueFactoryMethodName(String name){
        setFactoryMethodName(name);
        this.isFactoryMethodUnique = true;
    }
    /**
     * 业务意义
     * */
    public boolean isFactoryMethod(Method candidate){
        return candidate.getName().equals(getFactoryMethodName());
    }



    @Override
    public String getParentName() {
        return null;
    }

    /**
     * 业务意义
     * 1）factoryMethodToIntrospect是什么时候初始化？
     *    答复：doGetBeanNamesForType->isFactoryBean->predictBeanType->determineTargetType->getTypeForFactoryMethod 方法来初始化
     * 2）factoryMethodToIntrospect对应实例是？
     *    答复：方法实例{方法名->mvcResourceUrlProvider; resultType->ResourceUrlProvider; clazz->GangWebMvcConfigurationSupport}
     * */
    public Method getResolvedFactoryMethod(){
        return this.factoryMethodToIntrospect;
    }

}
